## Copyright 2002-2004 Andrew Loewenstern, All Rights Reserved
## Copyright 2007 Roee Shlomo, All Rights Reserved
# see LICENSE.txt for license information
import sys
from factory import Factory

DEBUG = False

class Khashmir:
    """
    Khashmir API
    """
    def __init__(self, host, port, dbDir = 'khashmir', ipv6_enable = False, upnp = 0, natpmp = False):
        self.host = host
        self.port = port
        self.factory = Factory(host, port, dbDir, ipv6_enable, upnp, natpmp)        
        
    def start(self):
        """
        Start DHT
        """
        if DEBUG:
            print "DHT: Starting"
        self.factory.start()
            
    def close(self):
        """
        Close DHT 
        """
        if DEBUG:
            print "DHT: Closing"
        self.factory.rawserver.add_task_prio(self.factory._close)

    def stats(self):
        """
        Returns the number of contacts in our routing table
        """
        return self.factory.stats()  

    def addContacts(self, nodes):
        for node in nodes:
            self.addContact(node[0], node[1])

    def addContact(self, host, port):
        """
        Ping this node and add the contact info to the table on pong!
        """
        if DEBUG:
            print "DHT: Adding contact - ", host, port
        return self.factory.addContact(host, port)
    
    def getPeers(self, infohash, callback, searchlocal = True, donecallback = None):
        """
        NOTE: USE getPeersAndAnnounce
        Returns the peers found for the infohash in global table
        callback will be called with a list of values for each peer that returns unique values
        final callback will be an empty list
        """
        if DEBUG:
            print "DHT: getPeers"
        self.factory.rawserver.add_task(self.factory.getPeers, 0, [infohash, callback, searchlocal, donecallback])

    def announcePeer(self, infohash, port, callback=None):
        """
        NOTE: USE getPeersAndAnnounce
        Announce that you're downloading the a torrent on a port
        @param callback - indicates nodes we got a response from
        """
        if DEBUG:
            print "DHT: announcePeer"
        self.factory.rawserver.add_task(self.factory.announcePeer, 0, [infohash, port, callback])

    def getPeersAndAnnounce(self, infohash, port, callback, searchlocal = True):
        """
        This is the method that is actually used ;)
        A combination of getPeers and announcePeer
        NOTE: keys expire every 30 minutes, so calling this method sooner is a good idea.
        """
        if DEBUG:
            print "DHT: getPeersAndAnnounce"

        def callback_wrapper(peers):
            if DEBUG:
                print "DHT: got %d peers" % len(peers)
            callback(peers)
            
        self.factory.rawserver.add_task(self.factory.getPeersAndAnnounce, 0, [infohash, port, callback_wrapper, searchlocal])

